# write by hasaki
# first edit on 2019-7-20
# last change on 2019-7-26
# 常鸿量化机回测引擎
import json
import csv
from datetime import datetime
import os
import sys

import pandas as pd

class HaBacktest:
    def __init__(self,strategyList,dataBase,log,evaluate):
        self.strategyList=strategyList            # type:list 策略列表
        self.dataBase=dataBase                    # type:class 数据库类
        self.simulateExchange=None                # type:class 模拟交易所，用于成交撮合
        self.log=log                              # type:class 日志系统，用于打印各种信息
        self.evaluate=evaluate                    # type:class 评价指标类

        # 回测计算相关的变量
        self.initCapital=0                        # type:float 初始化资金
        self.capital=0                            # type:float 当前总资产
        self.posDict={}                           # type:dict  持仓字典，支持多品种
        self.orderList=[]                         # type:list  委托列表，列表内是具体的委托字典
        self.orderDict={}                         # type:dict  委托字典，一次下单就是一个字典
        self.tradeList=[]                         # type:list  成交列表，列表内是具体的成交字典
        self.tradeDict={}                         # type:dict  成交字典，一次成交就是一个字典
        self.commision=0                          # type:float 总手续费
        self.feeRate=0                            # type:float 手续费比例

        # 回测过程辅助变量
        self.lastBar={}                           # type:dict 上一根bar
        self.endBar={}                            # type:dict 最后一根bar
        self.newBar={}                            # type:dict 最新一根bar
        self.isEnd=False                          # type:bool 是否轮询完历史数据
        self.countBar=0                           # type:int  计算当前回测到第几根bar
    
    # --------------------------------------------------------------------------------------
    # 回测引擎设置部分
    def init(self):
        '''回测引擎初始化设置'''
        self.simulateExchange=SimulateExchange(self)
        self.dataBase.init()
        self.log.init()
        self.evaluate.init()
    
    # --------------------------------------------------------------------------------------
    # 回测运行部分
    def run(self):
        self.log.allMethod('开始运行回测')
        for bar in self.dataBase.returnData():
            self.simulateExchange.crossOrder(self.newBar,self.orderList,self.tradeList)
            for strategy in self.strategyList:
                strategy.next(bar)
                strategyReturn=strategy.returnOrder()
                if strategyReturn:
                    self.orderList.append(strategyReturn)
                else:
                    continue
            self.simulateExchange.updateAccount()
            self.countBar+=1
            
        self.isEnd=True
        self.evaluate.start()
    
class SimulateExchange:
    def __init__(self,haEngine):
        self.engine=haEngine                      # type:class 使用模拟交易所的引擎
    
    # --------------------------------------------------------------------------------------
    # 撮合
    def crossOrder(self,bar,orderList,tradeList):
        '''撮合订单,第一个参数是K线，第二个参数是订单，第三个数据是成交列表
        模拟交易所的撮合价格是按照，如果是买单那么就按照最高价和开盘价的均价撮合
        如果是卖单就按照最低价和开盘价的均价撮合'''
        tradeTemp={}      # 临时的成交记录
        for order in orderList:
            if order['side']=='buy':
                realTradePrice=(bar['open']+bar['high'])/2
                tradeTemp['direction']=order['side']
                tradeTemp['price']=realTradePrice
                tradeTemp['vloume']=order['volume']
                tradeTemp['time']=bar['time']
                tradeList.append(tradeTemp)

            else:
                realTradePrice=(bar['open']+bar['low'])/2
                tradeTemp['direction']=order['side']
                tradeTemp['price']=realTradePrice
                tradeTemp['vloume']=order['volume']
                tradeTemp['time']=bar['time']
                tradeList.append(tradeTemp)
        pass

    # --------------------------------------------------------------------------------------
    # 更新交易所中的用户账户
    def updateAccount(self):
        '''更新用户账户信息'''
        pass

class Evaluate:
    def __init__(self,backtestEngine):
        self.engine=backtestEngine                  # type:class 常鸿量化机回测引擎
    
    def init(self):
        '''初始化设置'''
        print('评价指标模块初始化')

class Log:
    def __init__(self):
        self.allString=''                           # 需要用所有方法打印的字符串
    
    def init(self):
        pass
    
    def allMethod(self,string):
        '''用所有的日志方法打印字符串'''
        now=datetime.now()          # TODO : 这里要把datetime类型转换成字符串
        print('时间:{} 内容:{}'.format(string,now))
    
    def txt(self,string):
        '''保存字符串成txt文件'''
        pass

class DataBase:
    def __init__(self):
        pass
    
    def init(self):
        pass
    
    def feedCSV(self,fileName):
        '''读取CSV文件的数据'''
        pass